<?php


namespace App\Traits;


use Illuminate\Http\Exceptions\HttpResponseException;

trait ApiRespond
{

    /**
     * 状态码
     * @var int
     */
    protected $statusCode = 200;

    /**
     * 是否以抛出异常方式输出信息
     * @var bool
     */
    protected $throwMessage = false;

    /**
     * ===================================================================
     * API相关
     * ===================================================================
     */


    /**
     * 获取状态码
     * @author: Pako
     * @Email: admin@jqcool.net
     * @Date: 18-10-9 下午9:44
     * @return int
     */
    public function getStatusCode()
    {
        return $this->statusCode;
    }

    /**
     * 设置状态码
     * @author: Pako
     * @Email: admin@jqcool.net
     * @Date: 18-10-9 下午9:44
     * @param $statusCode
     * @return $this
     */
    public function setStatusCode($statusCode)
    {
        $this->statusCode = $statusCode;
        return $this;
    }

    /**
     * 是否以抛出异常方式输出信息
     * @author: Pako
     * @Email: admin@jqcool.net
     * @Date: 18-10-9 下午9:45
     * @return bool
     */
    public function isThrowMessage(): bool
    {
        return $this->throwMessage;
    }

    /**
     * 设置是否以抛出异常方式输出信息
     * @author: Pako
     * @Email: admin@jqcool.net
     * @Date: 18-10-9 下午9:45
     * @param bool $throwMessage
     * @return $this
     */
    public function setThrowMessage(bool $throwMessage)
    {
        $this->throwMessage = $throwMessage;
        return $this;
    }


    /**
     * 根据数据类型来产生响应
     * @author: Pako
     * @Email: admin@jqcool.net
     * @Date: 18-10-9 下午9:45
     * @param $data
     * @param int $errorCode
     * @param null $paramName
     * @param array $headers
     * @return \Illuminate\Http\JsonResponse|mixed
     */
    public function respondWith($data, $errorCode = 0, $paramName = null, array $headers = [])
    {
        if (!$data) {
            return $this->respondWithCode($errorCode);
        } elseif ($data instanceof Collection || $data instanceof LengthAwarePaginator || $data instanceof Model) {
            return $this->respondWithItem($data, $errorCode, $paramName, $headers);
        } elseif (is_array($data) || is_string($data) || is_numeric($data)) {
            return $this->respondWithData($data, $errorCode, $paramName, $headers);
        } elseif (is_object($data)) {
            return $this->respondWithObject($data, $errorCode, $paramName, $headers);
        } else {
            return $this->errorInternalError();
        }
    }

    /**
     * 根据数据类型来产生响应（抛出异常）
     * @author: Pako
     * @Email: admin@jqcool.net
     * @Date: 18-10-9 下午9:46
     * @param $data
     * @param int $errorCode
     * @param null $paramName
     * @param array $headers
     */
    public function throwRespondWith($data, $errorCode = 0, $paramName = null, array $headers = [])
    {
        $this->setThrowMessage(true)->respondWith($data, $errorCode, $paramName, $headers);
    }


    /**
     * 产生响应并处理Collection对象或Eloquent模型
     * @author: Pako
     * @Email: admin@jqcool.net
     * @Date: 18-10-9 下午9:47
     * @param $item
     * @param int $errorCode
     * @param null $paramName
     * @param array $headers
     * @return \Illuminate\Http\JsonResponse
     */
    public function respondWithItem($item, $errorCode = 0, $paramName = null, array $headers = [])
    {
        return $this->setStatusCode(200)->respondWithData($item->toArray(), $errorCode, $paramName, $headers);
    }

    /**
     * 产生响应并处理Collection对象或Eloquent模型（抛出异常）
     * @author: Pako
     * @Email: admin@jqcool.net
     * @Date: 18-10-9 下午9:47
     * @param $item
     * @param int $errorCode
     * @param null $paramName
     * @param array $headers
     * @return \Illuminate\Http\JsonResponse
     */
    public function throwRespondWithItem($item, $errorCode = 0, $paramName = null, array $headers = [])
    {
        return $this->setThrowMessage(true)->respondWithItem($item, $errorCode, $paramName, $headers);
    }

    /**
     * 产生响应并处理Collection对象或Eloquent模型
     * @author: Pako
     * @Email: admin@jqcool.net
     * @Date: 18-10-9 下午9:47
     * @param $object
     * @param int $errorCode
     * @param null $paramName
     * @param array $headers
     * @return \Illuminate\Http\JsonResponse|mixed
     */
    public function respondWithObject($object, $errorCode = 0, $paramName = null, array $headers = [])
    {
        if (method_exists($object, 'toArray')) {
            return $this->setStatusCode(200)->respondWithArray($object->toArray(), $errorCode, $headers);
        }

        return $this->setStatusCode(200)->respondWithData(json_decode(json_encode($object), true), $errorCode, $paramName, $headers);
    }

    /**
     * 产生响应并处理Collection对象或Eloquent模型（抛出异常）
     * @author: Pako
     * @Email: admin@jqcool.net
     * @Date: 18-10-9 下午9:47
     * @param $object
     * @param int $errorCode
     * @param null $paramName
     * @param array $headers
     * @return mixed
     */
    public function throwRespondWithObject($object, $errorCode = 0, $paramName = null, array $headers = [])
    {
        return $this->setThrowMessage(true)->throwRespondWithObject($object, $errorCode, $paramName, $headers);
    }

    /**
     * 产生响应并处理数组
     * @author: Pako
     * @Email: admin@jqcool.net
     * @Date: 18-10-9 下午9:48
     * @param array $array
     * @param int $errorCode
     * @param null $paramName
     * @param array $headers
     * @return \Illuminate\Http\JsonResponse
     */
    public function respondWithArray(array $array, $errorCode = 0, $paramName = null, array $headers = [])
    {
        return $this->setStatusCode(200)->respondWithData($array, $errorCode, $paramName, $headers);
    }

    /**
     * 产生响应并处理数组（抛出异常）
     * @author: Pako
     * @Email: admin@jqcool.net
     * @Date: 18-10-9 下午9:48
     * @param array $array
     * @param int $errorCode
     * @param null $paramName
     * @param array $headers
     * @return \Illuminate\Http\JsonResponse
     */
    public function throwRespondWithArray(array $array, $errorCode = 0, $paramName = null, array $headers = [])
    {
        return $this->setThrowMessage(true)->respondWithArray($array, $errorCode, $paramName, $headers);
    }

    /**
     * 产生响应并处字符串
     * @author: Pako
     * @Email: admin@jqcool.net
     * @Date: 18-10-9 下午9:48
     * @param $string
     * @param int $errorCode
     * @param null $paramName
     * @param array $headers
     * @return \Illuminate\Http\JsonResponse
     */
    public function respondWithString($string, $errorCode = 0, $paramName = null, array $headers = [])
    {
        return $this->setStatusCode(200)->respondWithData($string, $errorCode, $paramName, $headers);
    }

    /**
     * 产生响应并处字符串（抛出异常）
     * @author: Pako
     * @Email: admin@jqcool.net
     * @Date: 18-10-9 下午9:48
     * @param $string
     * @param int $errorCode
     * @param null $paramName
     * @param array $headers
     * @return \Illuminate\Http\JsonResponse
     */
    public function throwRespondWithString($string, $errorCode = 0, $paramName = null, array $headers = [])
    {
        return $this->setThrowMessage(true)->respondWithString($string, $errorCode, $paramName, $headers);
    }

    /**
     * 产生响应并处错误码
     * @author: Pako
     * @Email: admin@jqcool.net
     * @Date: 18-10-9 下午9:48
     * @param int $errorCode
     * @param null $paramName
     * @param array $headers
     * @return \Illuminate\Http\JsonResponse
     */
    public function respondWithCode($errorCode = 0, $paramName = null, array $headers = [], $replace = [])
    {
        return $this->respondWithData('', $errorCode, $paramName, $headers, $replace);
    }

    /**
     * 产生响应并处错误码（抛出异常）
     * @author: Pako
     * @Email: admin@jqcool.net
     * @Date: 18-10-9 下午9:49
     * @param int $errorCode
     * @param null $paramName
     * @param array $headers
     * @return \Illuminate\Http\JsonResponse
     */
    public function throwRespondWithCode($errorCode = 0, $paramName = null, array $headers = [])
    {
        return $this->setThrowMessage(true)->respondWithCode($errorCode, $paramName, $headers);
    }

    /**
     * 产生响应并处自定义错误信息
     * @author: Pako
     * @Email: admin@jqcool.net
     * @Date: 18-10-9 下午9:49
     * @param $message
     * @param string $data
     * @param null $errorCode
     * @param null $paramName
     * @param array $headers
     * @return \Illuminate\Http\JsonResponse
     */
    public function respondWithMessage($message, $data = '', $errorCode = null, $paramName = null, array $headers = [])
    {
        if ($errorCode == null) {
            $errorCode = 10100;
        }
        return $this->setStatusCode(422)->respondJson($data, $errorCode, $message, $paramName, $headers);
    }

    /**
     * 产生响应并处自定义错误信息（抛出异常）
     * @author: Pako
     * @Email: admin@jqcool.net
     * @Date: 18-10-9 下午9:49
     * @param $message
     * @param string $data
     * @param null $errorCode
     * @param null $paramName
     * @param array $headers
     * @return \Illuminate\Http\JsonResponse
     */
    public function throwRespondWithMessage($message, $data = '', $errorCode = null, $paramName = null, array $headers = [])
    {
        return $this->setThrowMessage(true)->respondWithMessage($message, $data, $errorCode, $paramName, $headers);
    }


    /**
     * 产生相应并处理数据
     * @author: Pako
     * @Email: admin@jqcool.net
     * @Date: 18-10-9 下午9:49
     * @param $data
     * @param $errorCode
     * @param null $paramName
     * @param array $headers
     * @return \Illuminate\Http\JsonResponse
     */
    private function respondWithData($data, $errorCode, $paramName = null, array $headers = [], $replace = [])
    {
        $message = trans('errcode.' . $errorCode, $replace);

        return $this->respondJson($data, $errorCode, $message, $paramName, $headers);
    }

    /**
     * 产生响应信息
     * @author: Pako
     * @Email: admin@jqcool.net
     * @Date: 18-10-9 下午9:50
     * @param $data
     * @param $errorCode
     * @param $message
     * @param null $errorParam
     * @param array $headers
     * @return \Illuminate\Http\JsonResponse
     */
    private function respondJson($data, $errorCode, $message, $errorParam = null, array $headers = [])
    {
        $responseDate = [];
        $responseDate['code'] = $errorCode;

        if (!empty($errorParam)) {
            $responseDate['param'] = $errorParam;
        }

        $responseDate['msg'] = $message;

        if (!empty($data)) {
            $responseDate['data'] = $data;
        }

        $response = response()->json($responseDate, $this->statusCode, $headers);

        if ($this->isThrowMessage()) {
            throw new HttpResponseException($response);
        } else {
            return $response;
        }

    }

    /**
     * 返回操作成功
     * @author: Pako
     * @Email: admin@jqcool.net
     * @Date: 18-10-9 下午9:50
     * @param int $errorCode
     * @param null $paramName
     * @param array $headers
     * @return \Illuminate\Http\JsonResponse
     */
    public function respondSuccess($errorCode = 0, $paramName = null, array $headers = [])
    {
        return $this->setStatusCode(200)->respondWithCode($errorCode, $paramName, $headers);
    }

    /**
     * 返回操作成功（抛出异常）
     * @author: Pako
     * @Email: admin@jqcool.net
     * @Date: 18-10-9 下午9:50
     * @param int $errorCode
     * @param null $paramName
     * @param array $headers
     * @return \Illuminate\Http\JsonResponse
     */
    public function throwRespondSuccess($errorCode = 0, $paramName = null, array $headers = [])
    {
        return $this->setThrowMessage(true)->respondSuccess($errorCode, $paramName, $headers);
    }

    /**
     * 返回错误
     * @author: Pako
     * @Email: admin@jqcool.net
     * @Date: 18-10-9 下午9:50
     * @param int $errorCode
     * @param null $paramName
     * @param array $headers
     * @return \Illuminate\Http\JsonResponse
     */
    public function respondError($errorCode = 10101, $paramName = null, array $headers = [], $replace = [])
    {
        return $this->setStatusCode(422)->respondWithCode($errorCode, $paramName, $headers, $replace);
    }

    /**
     * 返回错误（抛出异常）
     * @author: Pako
     * @Email: admin@jqcool.net
     * @Date: 18-10-9 下午9:50
     * @param int $errorCode
     * @param null $paramName
     * @param array $headers
     * @return \Illuminate\Http\JsonResponse
     */
    public function throwRespondError($errorCode = 10101, $paramName = null, array $headers = [], $replace = [])
    {
        return $this->setThrowMessage(true)->respondError($errorCode, $paramName, $headers, $replace);
    }

    /**
     * 请求不允许(403)
     * @author: Pako
     * @Email: admin@jqcool.net
     * @Date: 18-10-9 下午9:51
     * @param int $errorCode
     * @return \Illuminate\Http\JsonResponse
     */
    public function errorForbidden($errorCode = 403)
    {
        return $this->setStatusCode(403)->respondWithCode($errorCode);
    }

    /**
     * 请求不允许(403)
     * @author: Pako
     * @Email: admin@jqcool.net
     * @Date: 18-10-9 下午9:51
     * @param int $errorCode
     * @return \Illuminate\Http\JsonResponse
     */
    public function throwErrorForbidden($errorCode = 403)
    {
        return $this->setThrowMessage(true)->errorForbidden($errorCode);
    }

    /**
     * 服务器产生内部错误(500)
     * @author: Pako
     * @Email: admin@jqcool.net
     * @Date: 18-10-9 下午9:51
     * @param int $errorCode
     * @return \Illuminate\Http\JsonResponse
     */
    public function errorInternalError($errorCode = 500)
    {
        return $this->setStatusCode(500)->respondWithCode($errorCode);
    }

    /**
     * 服务器产生内部错误(500)（抛出异常）
     * @author: Pako
     * @Email: admin@jqcool.net
     * @Date: 18-10-9 下午9:51
     * @param int $errorCode
     * @return \Illuminate\Http\JsonResponse
     */
    public function throwErrorInternalError($errorCode = 500)
    {
        return $this->setThrowMessage(true)->errorInternalError($errorCode);
    }

    /**
     * 没有找到指定资源(404)
     * @author: Pako
     * @Email: admin@jqcool.net
     * @Date: 18-10-9 下午9:51
     * @param int $errorCode
     * @return \Illuminate\Http\JsonResponse
     */
    public function errorNotFound($errorCode = 404)
    {
        return $this->setStatusCode(404)->respondWithCode($errorCode);
    }

    /**
     * 没有找到指定资源(404)（抛出异常）
     * @author: Pako
     * @Email: admin@jqcool.net
     * @Date: 18-10-9 下午9:52
     * @param int $errorCode
     * @return \Illuminate\Http\JsonResponse
     */
    public function throwErrorNotFound($errorCode = 404)
    {
        return $this->setThrowMessage(true)->errorNotFound($errorCode);
    }

    /**
     * 请求授权失败(401)
     * @author: Pako
     * @Email: admin@jqcool.net
     * @Date: 18-10-9 下午9:52
     * @param int $errorCode
     * @return \Illuminate\Http\JsonResponse
     */
    public function errorUnauthorized($errorCode = 401)
    {
        return $this->setStatusCode(401)->respondWithCode($errorCode);
    }

    /**
     * 请求授权失败(401)（抛出异常）
     * @author: Pako
     * @Email: admin@jqcool.net
     * @Date: 18-10-9 下午9:52
     * @param int $errorCode
     * @return \Illuminate\Http\JsonResponse
     */
    public function throwErrorUnauthorized($errorCode = 401)
    {
        return $this->setThrowMessage(true)->errorUnauthorized($errorCode);
    }


    /**
     * 错误请求(400)
     * @author: Pako
     * @Email: admin@jqcool.net
     * @Date: 18-10-9 下午9:52
     * @param int $errorCode
     * @return \Illuminate\Http\JsonResponse
     */
    public function errorWrongArgs($errorCode = 400)
    {
        return $this->setStatusCode(400)->respondWithCode($errorCode);
    }

    /**
     * 错误请求(400)（抛出异常）
     * @author: Pako
     * @Email: admin@jqcool.net
     * @Date: 18-10-9 下午9:52
     * @param int $errorCode
     * @return \Illuminate\Http\JsonResponse
     */
    public function throwErrorWrongArgs($errorCode = 400)
    {
        return $this->setThrowMessage(true)->errorWrongArgs($errorCode);
    }

    /**
     * 无法处理的请求实体(422)
     * @author: Pako
     * @Email: admin@jqcool.net
     * @Date: 18-10-9 下午9:53
     * @param int $errorCode
     * @return \Illuminate\Http\JsonResponse
     */
    public function errorUnprocessableEntity($errorCode = 422)
    {
        return $this->setStatusCode(422)->respondWithCode($errorCode);
    }

    /**
     * 无法处理的请求实体(422)（抛出异常）
     * @author: Pako
     * @Email: admin@jqcool.net
     * @Date: 18-10-9 下午9:53
     * @param int $errorCode
     * @return \Illuminate\Http\JsonResponse
     */
    public function throwErrorUnprocessableEntity($errorCode = 422)
    {
        return $this->setThrowMessage(true)->errorUnprocessableEntity($errorCode);
    }
}